package com.hutu.kboshi.controller;


import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hutu.kboshi.adapter.QuestionBankBuilder;
import com.hutu.kboshi.common.BaseResponse;
import com.hutu.kboshi.common.ErrorCode;
import com.hutu.kboshi.common.ResultUtils;
import com.hutu.kboshi.common.constant.CommonConstant;
import com.hutu.kboshi.common.constant.UserConstant;
import com.hutu.kboshi.common.exception.ThrowUtils;
import com.hutu.kboshi.pojo.dto.question.QuestionQueryRequest;
import com.hutu.kboshi.pojo.dto.questionbank.QuestionBankAddRequest;
import com.hutu.kboshi.pojo.dto.questionbank.QuestionBankDelRequest;
import com.hutu.kboshi.pojo.dto.questionbank.QuestionBankEditRequest;
import com.hutu.kboshi.pojo.dto.questionbank.QuestionBankQueryRequest;
import com.hutu.kboshi.pojo.dto.questionbank.QuestionBankUpdateRequest;
import com.hutu.kboshi.pojo.entity.Question;
import com.hutu.kboshi.pojo.entity.QuestionBank;
import com.hutu.kboshi.pojo.vo.QuestionBankVO;
import com.hutu.kboshi.pojo.vo.QuestionVO;
import com.hutu.kboshi.service.QuestionBankService;
import com.hutu.kboshi.service.QuestionService;
import com.jd.platform.hotkey.client.callback.JdHotKeyStore;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 题库接口
 */
@RestController
@RequestMapping("/questionBank")
@Slf4j
@RequiredArgsConstructor
public class QuestionBankController {

    private final QuestionBankService questionBankService;

    private final QuestionService questionService;



    /**
     * 创建题库 必须是管理员&&拥有add权限
     * TODO 给普通用户一个公共题库
     *
     * @param questionBankAddRequest
     * @param request
     * @return
     */
    @PostMapping("/add")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    @SaCheckPermission(value = {UserConstant.ADD_PERMISSION, UserConstant.ALL_PERMISSION},mode = SaMode.OR)
    public BaseResponse<Long> addQuestionBank(@RequestBody QuestionBankAddRequest questionBankAddRequest, HttpServletRequest request) {
        QuestionBank questionBank = QuestionBankBuilder.builderQuestionBankAddRequestToQuestionBank(questionBankAddRequest);
        long loginId = StpUtil.getLoginIdAsLong();
        questionBank.setCreateBy(loginId);
        // 写入数据库
        questionBankService.save(questionBank);
        return ResultUtils.success(questionBank.getId());
    }

    /**
     * 删除题库 属于核心 必须要求是管理员&&拥有全部权限&&本人也无法删除
     * 还需要清除 -TODO 所有题目  - 和题目关联表
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    @SaCheckPermission(value = {UserConstant.ALL_PERMISSION})
    public BaseResponse<Boolean> deleteQuestionBank(@Validated @RequestBody QuestionBankDelRequest deleteRequest, HttpServletRequest request) {
        long id = deleteRequest.getId();
        questionBankService.removeQuestionBankById(id);
        return ResultUtils.success(Boolean.TRUE);
    }

    /**
     * 更新题库（仅管理员可用）
     *
     * @param questionBankUpdateRequest
     * @return
     */
    @PostMapping("/update")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    @SaCheckPermission(value = {UserConstant.UPDATE_PERMISSION, UserConstant.ALL_PERMISSION},mode = SaMode.OR)
    public BaseResponse<Boolean> updateQuestionBank(@Validated @RequestBody QuestionBankUpdateRequest questionBankUpdateRequest) {
        QuestionBank questionBank = QuestionBankBuilder.builderQuestionBankUpdateRequestToQuestionBank(questionBankUpdateRequest);
        // 操作数据库
        boolean result = questionBankService.updateById(questionBank);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(Boolean.TRUE);
    }

    /**
     * 公共接口
     * 根据 id 获取题库
     * @param questionBankQueryRequest
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<QuestionBankVO> getQuestionBankVOById(QuestionBankQueryRequest questionBankQueryRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(questionBankQueryRequest == null, ErrorCode.PARAMS_ERROR);
        Long id = questionBankQueryRequest.getId();
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        // 生成 key
        String key = CommonConstant.HOT_KEY_BANK + id;
        // 如果是热 key
        if (JdHotKeyStore.isHotKey(key)) {
            // 从本地缓存中获取缓存值
            Object cachedQuestionBankVO = JdHotKeyStore.get(key);
            if (cachedQuestionBankVO != null) {
                // 如果缓存中有值，直接返回缓存的值
                return ResultUtils.success((QuestionBankVO) cachedQuestionBankVO);
            }
        }
        // 查询数据库
        QuestionBank questionBank = questionBankService.getQuestionBankById(id);
        ThrowUtils.throwIf(questionBank == null, ErrorCode.NOT_FOUND_ERROR);
        // 查询题库封装类
        QuestionBankVO questionBankVO = QuestionBankVO.objToVo(questionBank);
        QuestionQueryRequest questionQueryRequest = new QuestionQueryRequest();
        questionQueryRequest.setQuestionBankId(id);
        questionQueryRequest.setPageSize(questionBankQueryRequest.getPageSize());
        questionQueryRequest.setCurrent(questionBankQueryRequest.getCurrent());
        Page<Question> questionPage = questionService.listQuestionByPage(questionQueryRequest);
        Page<QuestionVO> questionVOPage = questionService.getQuestionVOPage(questionPage, request);
        questionBankVO.setQuestionPage(questionVOPage);
        // 设置本地缓存（如果不是热 key，这个方法不会设置缓存）
        JdHotKeyStore.smartSet(key, questionBankVO);
        // 获取封装类
        return ResultUtils.success(questionBankVO);
    }


    /**
     * 分页获取题库列表
     * 首页展示,只传递 tag,根据tag来查询
     * @param questionBankQueryRequest
     * @return
     */
/*    @PostMapping("/list/page/vo")
    public BaseResponse<Page<QuestionBank>> listQuestionBankVOByPage(@RequestBody QuestionBankQueryRequest questionBankQueryRequest) {
        Page<QuestionBank> questionBankPage = questionBankService.pages(questionBankQueryRequest);
        // 获取封装类
        return ResultUtils.success(questionBankPage);
    }*/
    @PostMapping("/list/page/vo")
    public BaseResponse<Page<QuestionBankVO>> listQuestionBankVOByPage(@RequestBody QuestionBankQueryRequest questionBankQueryRequest,
                                                                       HttpServletRequest request) {
        long current = questionBankQueryRequest.getCurrent();
        long size = questionBankQueryRequest.getPageSize();
        // 限制爬虫
        ThrowUtils.throwIf(size > 200, ErrorCode.PARAMS_ERROR);
        // 查询数据库
        Page<QuestionBank> questionBankPage = questionBankService.pagess(questionBankQueryRequest);
        // 获取封装类
        return ResultUtils.success(questionBankService.getQuestionBankVOPage(questionBankPage, request));
    }

    /**
     * 编辑题库（给管理员使用 TODO）
     * @param questionBankEditRequest
     * @param request
     * @return
     */
    @PostMapping("/edit")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    @SaCheckPermission(value = {UserConstant.UPDATE_PERMISSION, UserConstant.ALL_PERMISSION},mode = SaMode.OR)
    public BaseResponse<Boolean> editQuestionBank(@RequestBody QuestionBankEditRequest questionBankEditRequest, HttpServletRequest request) {
        QuestionBank questionBank = QuestionBankBuilder.builderQuestionBankEditRequestToQuestionBank(questionBankEditRequest);
        return ResultUtils.success(questionBankService.checkProcessAndUpdate(questionBank));
    }
}
